package com.freeleaps.devops

/**
 * 变更组件检测器类
 * 负责检测在最近的提交中哪些组件发生了变更
 * 通过分析Git提交历史，确定需要重新构建的组件
 * 支持按需执行模式，只对发生变更的组件执行构建流程
 * 提供高效的变更检测机制，避免不必要的构建资源浪费
 */
class ChangedComponentsDetector {
  // Jenkins Pipeline的steps对象，用于调用Jenkins内置功能
  def steps
  // 工作空间路径，Git仓库的根目录
  def workspace

  /**
   * 构造函数
   * @param steps Jenkins Pipeline的steps对象
   */
  ChangedComponentsDetector(steps) {
    this.steps = steps
  }

  /**
   * 检测发生变更的组件
   * 通过比较最近两次提交的文件变更，确定哪些组件需要重新构建
   * 
   * @param workspace Git仓库的工作空间路径
   * @param components 所有组件的配置列表
   * @return 发生变更的组件名称列表
   */
  def detect(workspace, components) {
    // 使用Set集合存储变更的组件，避免重复
    def changedComponents = [] as Set

    // 切换到Git仓库目录
    steps.dir(workspace) {
      // 使用Git命令获取变更文件列表
      // 需要插件：Pipeline Plugin (基础插件) - 提供sh功能，用于执行Shell命令
      // git diff --name-only HEAD~1 HEAD 命令详解：
      // - git diff: Git差异比较命令
      // - --name-only: 只显示文件名，不显示具体变更内容
      // - HEAD~1: 上一个提交（父提交）
      // - HEAD: 当前提交（最新提交）
      // 这个命令会返回从上一个提交到当前提交之间所有发生变更的文件路径
      def changedFiles = steps.sh(script: 'git diff --name-only HEAD~1 HEAD', returnStdout: true)
        .trim()        // 去除首尾空白字符
        .split('\n')   // 按换行符分割，得到文件路径数组

      // 记录变更的文件列表，用于调试和日志
      steps.log.info("ChangedComponentsDetector", "Changed files: ${changedFiles}")
      
      // 遍历所有变更的文件
      changedFiles.each { file ->
        // 遍历所有组件配置
        components.each { component ->
          // 检查文件是否属于当前组件
          // 通过检查文件路径是否以组件根目录开头来判断
          // 例如：如果文件路径是 "frontend/src/app.js"，组件根目录是 "frontend"
          // 则 file.startsWith("frontend/") 返回 true
          if (file.startsWith("${component.root}/")) {
            // 将组件名称添加到变更组件集合中
            changedComponents.add(component.name)
          }
        }
      }
    }

    // 将Set转换为List并返回
    return changedComponents.toList()
  }
}